from functools import reduce
import jwt
import time
import redis
from django.conf import settings
from django.core.paginator import Paginator
from gevent import os
from rest_framework.response import Response
from rest_framework.views import APIView
from goods.serializer import CarouselSer, GoodsSer, GoodImgSer, GoodLikeSer, CategorySer
from goods.models import Carousel, Category, Goods, GoodImg, GoodLike, Order, OrderGoods
from users.models import Addr

# 轮播图
class CarouselView(APIView):
    def get(self,request):
        carouseles = Carousel.objects.all()
        ser = CarouselSer(carouseles,many=True)
        return Response({'code':200,'msg':'轮播图成功加载','carousel':ser.data})

# 商品列表
class GoodsList(APIView):
    def post(self,request):
        params = request.data.get('params')
        cate_name = params['categoryName']
        try:
            cate = Category.objects.get(cate_name=cate_name)
        except Exception as e:
            print(e)
            return Response({'msg':'此商品类别不存在','code': 204})
        goods_query_set = cate.goods_set.all()[0:7]
        goods_ser = GoodsSer(goods_query_set,many=True)  #many=True，序列化多个对象集合
        return Response(goods_ser.data)

# 热门商品
class HotGoods(APIView):
    def post(self,request):
        params = request.data.get('params')
        cate_name = params['categoryName']
        category_objs = [Category.objects.get(cate_name=i) for i in cate_name]
        temp_list = [cate.goods_set.all() for cate in category_objs]
        r = reduce(lambda x, y: x | y, temp_list).order_by("-count")[0:7]
        # print('合并的查询集:',r)
        goods_ser = GoodsSer(r,many=True)
        return Response(goods_ser.data)

# 商品相关信息
class OneGoods(APIView):
    def get(self,request):
        # 获取前端传来的商品id
        id = request.query_params['productID']
        # 查询数据库
        try:
            id=Goods.objects.get(id=id)
        except Exception as e:
            return Response({'code':404,'msg':'没有获取到信息'})
        ser = GoodsSer(id)
        return Response(ser.data)

# # 获取商品详情轮播图
class GoodsImgView(APIView):
    def get(self,request):
        id = request.query_params['productID']
        query_set = GoodImg.objects.filter(good_id=id)
        ser = GoodImgSer(query_set,many=True)
        return Response(ser.data)

# 历史记录
class HistoryView(APIView):
    def post(sel,requestf):
        id = requestf.data['productID']
        token = requestf.data['token']
        try:
            payload = jwt.decode(token,settings.SECRET_KEY,algorithms='HS256')
            if int(time.time())>payload['time']:
                return Response({'code':400,'msg':'token过期'})
            r = redis.Redis(host='127.0.0.1',port=6379)
            key = 'history:%s'%payload['id']
            r.lrem(key,0,id)
            r.lpush(key,id)
            r.ltrim(key,0,10)
            return Response({'code':200,'msg':"查看历史记录成功"})
        except Exception as e:
            return Response({'code':400,'msg':'历史记录失败'})

# 检测用户登录的装饰器
def check_user(func):
    def check(cls,request):
        token = request.META.get('HTTP_TOKEN')
        try:
            paLoad = jwt.decode(token,settings.SECRET_KEY,algorithms='HS256')
            if paLoad['time'] < int(time.time()):
                return Response({'code':400,'msg':'token失败'})
        except Exception as e:
            return Response({'code':400,'msg':'验证失败'})
        return func(cls,request,paLoad)
    return check

# 收藏
class LikeView(APIView):
    @check_user
    def get(self,request,payload):
        # 获取用户当前收藏的商品信息
        query_set = GoodLike.objects.filter(user_id=payload['id'])
        ser = GoodLikeSer(query_set,many=True)
        json_data = []
        for item in ser.data:
            json_data.append(item['goods'])
        return Response({
            'code':200,
            'msg':'获取成功',
            'collectList':json_data
        })
    # 添加
    def post(self, request):
        id = request.data.get('productID')
        token = request.META.get('HTTP_TOKEN')
        try:
            goods_info = Goods.objects.get(id=id)
        except:
            return Response({'code':400,'msg':'商品不存在'})
        try:
            # 解码并获取负载荷
            payload = jwt.decode(token,settings.SECRET_KEY,algorithms='HS256')
            # 判断一下time，是否过期
            if payload['time'] < int(time.time()):
                return Response({'code':400,'msg':"token失败"})
            user_id = payload['id']
            goods_id = goods_info.id
            count = GoodLike.objects.filter(user_id = user_id,goods_id = goods_id).count()
            if count > 0:
                return Response({'code':400,'msg':"当前商品已经收藏"})
            GoodLike.objects.create(user_id=user_id,goods_id=goods_id)
            return Response({'code':200,'msg':'收藏成功'})
        except Exception as e:
            return Response({'code':400,'msg':'token有误'})
    # 删除
    @check_user
    def delete(self,request,paload):
        id = request.data.get('productID')
        GoodLike.objects.filter(user_id = paload['id']).filter(goods_id = id).delete()
        return Response({'code':200,'msg':'删除成功'})

# 购物车
class Cart(APIView):
    # 添加
    @check_user  # 装饰器 检测用户登录
    def post(self,request,payLoad):  # payLoad 是检测用户登陆时 自动帮我们传入
        user_id = payLoad['id']  # 用户id
        good_id = request.data.get('productID')  # 商品id
        goods_info = Goods.objects.filter(id=good_id).first()
        if not goods_info:
            return Response({'code':400,'msg':'商品不存在'})
        key ='cart:%s'%user_id  # 定义redis的key用来存放数据
        r = redis.Redis()
        goods_count = r.hget(key,good_id)  # 获取redis中 当前用户 当前商品 在购物车中的数量
        if not goods_count:
            r.hset(key,good_id,str(1))  # 初次写入
            return Response({'code':200,'msg':'加入购物车ok',
                             'shoopingCartData':{
                                 "id": goods_info.id,
                                 "productID": goods_info.id,
                                 "productName": goods_info.sku_name,
                                 "productImg": goods_info.img,
                                 "price": goods_info.selling_price,
                                 'num': 1,
                                 'maxNum': goods_info.stock,
                                 'check': True,
                             }})
        else:
            r.hincrby(key,good_id)
            return Response({'code':201,'msg':'商品已经在购物车，数量加1'})

    # 查询
    @check_user
    def get(self,request,payload):
        user_id = payload['id']
        key = 'cart:%s'%user_id
        r = redis.Redis()
        good_list = r.hgetall(key)
        select_key = 'cart_select:%s'%user_id
        select_good = r.smembers(select_key)
        check_all = []
        for i in select_good:
            check_all.append(int(i.decode()))
        print(check_all)
        cart_all = []
        for key,val in good_list.items():
            good_id = int(key.decode())
            goods_count = int(val.decode())
            goods_info = Goods.objects.filter(id=good_id).first()
            if not goods_info:
                continue
            check = False
            if goods_info.id in check_all:
                check = True
            cart_all.append({
                'id': goods_info.id,
                'productID': goods_info.id,
                'productName': goods_info.sku_name,
                'productImg': goods_info.img,
                'price': goods_info.selling_price,
                'num': goods_count,
                'maxNum': goods_info.stock,
                'check': check,
            })
        return Response({'code':200,'msg':'购物车数据获取成功','shoppingCartData':cart_all})

    # 修改
    @check_user
    def put(self,request,payload):
        user_id = payload['id']
        goods_id = request.data.get('productID')
        num = request.data.get('num')
        good_info = Goods.objects.filter(id=goods_id).first()
        if not good_info:
            return Response({"code": 400,"msg": "该商品不存在"})
        if good_info.stock < num:
            return Response({"code": 400,"msg": "库存不足"})
        r = redis.Redis()
        key = "cart:%s" % user_id
        try:
            r.hset(key, goods_id, num)
            return Response({"code": 200,"msg": "修改购物车数量成功，当前数量%s" % num})
        except:
            return Response({"code": 400,"msg": "修改购物车数量失败"})

    # 删除
    @check_user
    def delete(self,request,paload):
        user_id = paload['id']
        good_id = request.data.get('projectID')
        r = redis.Redis()  # 连接数据库
        key = 'cart%s'%user_id
        r.hdel(key,good_id)
        return Response({'code':200,'msg':'删除成功'})

# 全选
class CartSelect(APIView):
    @check_user
    def post(self,request,paload):
        user_id = paload['id']  # 用户id
        check = request.data.get('val')  # 获取前端传过来的全选不全选状态
        r = redis.Redis()  # 链接数据库
        key = 'cart:%s'%user_id  #当前用户购物车的key
        select_key = 'cart_select:%s'%user_id  # 定义当前用户选中购物车的key
        cart_goods = r.hkeys(key)  # 获取购物车中所有商品id
        cart_goods_int = []  # 用来存放转义后的goods_id
        for id in cart_goods:
            id_str = id.decode()  # 把bute转化成str类型
            id_int = int(id_str)  # 把str转化成int
            cart_goods_int.append(id_int)  # 把good_id追加到列表中

        if check:
            try:
                r.sadd(select_key,*cart_goods_int)  # 一次性把所有商品ID全部作为参数传进去
                return Response({'code':200,'msg':'全选成功'})
            except:
                return Response({'code':400,'msg':'全选失败'})
        else:
            try:
                r.srem(select_key,*cart_goods_int)
                return Response({'code':200,'msg':'取消全选成功'})
            except:
                return Response({'code':400,'msg':'取消全选失败'})

# 分类
class CateView(APIView):
    def get(self,request):
        query_set = Category.objects.all()
        ser = CategorySer(query_set,many=True)
        return Response({'code':200,'msg':'ok','category':ser})

# 全部商品
class GoodsAllView(APIView):
    def post(self,request):
        # 获取页码和每页数据条数
        page_size = request.data.get('pageSize')  # 每页条数
        cur_page = request.data.get('currenPage')  # 当前页数
        goods_list = Goods.objects.all()
        goods_page = Paginator(goods_list,per_page=page_size)
        page_info = goods_page.page(cur_page)
        goods_ser = GoodsSer(page_info.object_list,many=True)
        return Response({'code':200,'msg':'ok','product':goods_ser.data,'total':goods_list.count()})

# 分类下的商品
class CateGoodsView(APIView):
    def post(self,request):
        # 查询分类id
        cate_id = request.data.get('categoryID')
        page_size = request.data.get('pageSize')  # 每页条数
        cur_page = request.data.get('currentPage')  # 当前页数
        # 查询分类下的商品
        goods_list = Goods.objects.filter(cate_id__in=cate_id).all()
        goods_page = Paginator(goods_list,per_page=page_size)
        page_info = goods_page.page(cur_page)
        # 序列化
        good_ser = GoodsSer(page_info.object_list,many=True)
        return Response({'code':200,'msg':'ok','product':good_ser.data,'total':goods_list.count()})


